package UDPEchoServerLient0406;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * Description:
 * User:岁亮亮
 * Date:2025-04-06
 * TIME:13:09
 */
public class UDPEchoServer2 {

    //创建一个socket对象, socket对象是java封装操作系统提供的网络编程api 即传输层提供的对udp网络编程的api
    //操作系统有这样一个socket文件 抽象表示了网卡这样的硬件设施 通过对socket文件的读写就是 网卡接受数据和发送数据的过程
    //对sockey对象在内存中的操作 就是对操作系统中的socket文件的读写 也相当于间接影响对网卡这样的硬件设备操作

    DatagramSocket socket = null;

    public UDPEchoServer2(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        //服务器是7 * 24 不停的工作 因此while(true)
        //每次循环执行的过程就是服务器处理一次客户端发来的请求 并通过请求做出响应的过程
        while(true){
            //1.首先(如果有)接受客户端发来的请求
            //1.1 接收关于UDP 的请求 UDP协议的是基于UDP数据报的 每次发送接收的基本单位是一个UDP数据报
            //构造一个接收UDP请求的数据报
            DatagramPacket requestPacket = new DatagramPacket(new byte[1024], 1024);
            /**
             * 1.2通过对socket对象的操作 接收请求
             * 1.2.1可以看出packet对象 相当于一个输出型参数 接收UDP数据报(内部有一个字节数组构成)
             * 1.2.2 socket.receive()方法 读取客户端发来的请求
             *       就是服务器通过网卡接收发送来的数据报 数据报通过网卡传到上层协议 这样数据包通过层次的封装分用 传递到传输层
             *       传输层即操作系统内核 操作系统内核位接收的数据报分配一个缓冲区 生产者消费者模型
             *       receive()方法 就是在这个缓冲区读取数据报 没有就进入阻塞状态 等待请求
             */

            socket.receive(requestPacket);

            //2.通过请求 执行对应的业务逻辑 构造出响应
            String request = new String(requestPacket.getData(),0, requestPacket.getLength());
            String response = process(request);
            //2.1 发送响应的UDP数据报 要有目标主机的IP和port 这里将请求中的IP和port 当作响应的目的IP和目标Port
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length
                                                               ,requestPacket.getSocketAddress());
            //3.发送响应 进入下一次循环继续处理请求
            socket.send(responsePacket);

            //打印日志
            System.out.printf("[%s : %d req : %s  resp : %s",requestPacket.getAddress(),requestPacket.getPort()
                                                            ,request,response);
        }
    }

    /**
     * 根据请求 执行对应业务逻辑
     * 这里逻辑 就是 发送的请求是什么 响应就是什么
     * @param request 请求
     * @return
     */
    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UDPEchoServer2 server2 = new UDPEchoServer2(9090);
        server2.start();
    }
}
